package org.shoukaiseki.ddcs.actuator.allocation;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.shoukaiseki.ddcs.actuator.config.ConfiguratorField;
import org.shoukaiseki.ddcs.actuator.config.ConfiguratorTable;
import org.shoukaiseki.ddcs.actuator.conn.ConnectionFactory;
import org.shoukaiseki.ddcs.actuator.model.Tableindex;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

/**
 * org.shoukaiseki.ddcs.actuator.AllocationSave <br>
 *  分配保存,将一个model中的字段按照排序配置分别保存到相应的表中
 * @author 蒋カイセキ    Japan-Tokyo  2018-07-23 22:29:01<br>
 * ブログ http://shoukaiseki.blog.163.com/<br>
 * E-メール jiang28555@Gmail.com<br>
 **/

public class AllocationSave {

    /**
     * 共享数据库链接
     */
    private static Map<String,Connection> sharedConnectionMap=null;

    private ConfiguratorTable ct;
    private Connection connectionConfig;

    Map<String,PreparedStatement> configuratorPreparedStatementMap= Maps.newHashMap();

    Map<String,PreparedStatement> sharedBatchPrepareStatementMap= Maps.newHashMap();


    Map<String,Connection> sharedBatchConnection= Maps.newHashMap();

    PreparedStatement indexUpdatePreparedStatement=null;



    private String tablename;

    public AllocationSave(String tablename) throws SQLException {
        this.tablename=tablename;
        this.ct=new ConfiguratorTable("user");
        connectionConfig = ConnectionFactory.getConnectionConfig();
    }


    public void addBySharedBatch(Object model) throws Exception {


        for (String attname:ct.getFieldconfig().keySet()){
            ConfiguratorField cf = ct.getFieldconfig().get(attname);

            PreparedStatement psIndex=createConfiguratorPreparedStatement(cf);
            psIndex.setString(1,tablename);
            psIndex.setString(2,attname);
            PropertyDescriptor pd = new PropertyDescriptor(attname.toLowerCase(), model.getClass());
            Object value=pd.getReadMethod().invoke(model);
            psIndex.setObject(3,value);


            ResultSet rs = psIndex.executeQuery();
            System.out.println(attname+"="+value);
            Tableindex beforeTableindex=null;
            Tableindex afterTableindex=null;

            boolean turn=false;
            int i=0;
            String ddcs_datasource=null;
            String ddcs_dstablename=null;
            int sn=0;

            Tableindex sortTableindex=null;
            int sortIndex=0;

            PreparedStatement ps = getIndexUpdatePreparedStatement();

            List<Tableindex> list= Lists.newArrayList();
            while (rs.next()){
                i++;
                Tableindex tableindex=new Tableindex();
                tableindex.setDdcs_datasource(rs.getString("ddcs_datasource"));
                tableindex.setDdcs_dstablename(rs.getString("ddcs_dstablename"));
                tableindex.setDdcs_ismax(rs.getBoolean("ddcs_ismax"));
                tableindex.setSn(rs.getInt("sn"));
                tableindex.setDdcs_fieldvalue(rs.getString("ddcs_fieldvalue"));
                list.add(tableindex);

                if(tableindex.getDdcs_datasource()==null){
                    sortTableindex=tableindex;
                    sortIndex=i;
                    turn=true;
                }

                if(turn&&sortIndex+2==i){
                    break;
                }


            }


            System.out.println("i="+i+",index="+sortIndex);


            if(sortIndex%2==1){
                if(list.size()>sortIndex){
                    afterTableindex = list.get(sortIndex);
                    ddcs_dstablename=afterTableindex.getDdcs_dstablename();
                    ddcs_datasource=afterTableindex.getDdcs_datasource();
                    sn=afterTableindex.getSn();

                    System.out.println("afterTableindex1="+JSONObject.toJSONString(afterTableindex));
                    ps.setObject(1,value);
                    ps.setObject(2,tablename);
                    ps.setObject(3,attname);
                    ps.setInt(4,sn);
                    ps.addBatch();
                    System.out.print("a1="+value);
                    System.out.print(",2="+tablename);
                    System.out.print(",3="+attname);
                    System.out.println(",4="+sn);


                    Tableindex tempTableindex = list.get(sortIndex+1);
                    if(tempTableindex.getDdcs_fieldvalue()==null&&afterTableindex.getDdcs_fieldvalue()!=null){
                        ps.setObject(1,afterTableindex.getDdcs_fieldvalue());
                        ps.setObject(2,tablename);
                        ps.setObject(3,attname);
                        ps.setInt(4,tempTableindex.getSn());
                        ps.addBatch();
                        System.out.print("b1="+afterTableindex.getDdcs_fieldvalue());
                        System.out.print(",2="+tablename);
                        System.out.print(",3="+attname);
                        System.out.println(",4="+tempTableindex.getSn());
                    }
                }else{

                    beforeTableindex = list.get(sortIndex-2);
                    ddcs_dstablename=beforeTableindex.getDdcs_dstablename();
                    ddcs_datasource=beforeTableindex.getDdcs_datasource();
                    sn=beforeTableindex.getSn();

                    System.out.println("afterTableindex1b="+JSONObject.toJSONString(beforeTableindex));
                    ps.setObject(1,value);
                    ps.setObject(2,tablename);
                    ps.setObject(3,attname);
                    ps.setInt(4,sn);
                    ps.addBatch();
                    System.out.print("a1="+value);
                    System.out.print(",2="+tablename);
                    System.out.print(",3="+attname);
                    System.out.println(",4="+sn);
                }
                ps.executeBatch();
            }else{
                afterTableindex = list.get(sortIndex);
                ddcs_dstablename=afterTableindex.getDdcs_dstablename();
                ddcs_datasource=afterTableindex.getDdcs_datasource();

                System.out.println("afterTableindex2="+JSONObject.toJSONString(afterTableindex));
                if(afterTableindex.getDdcs_fieldvalue()==null){
                    sn=afterTableindex.getSn();
                    System.out.println("after1.datasource="+ddcs_datasource);
                    ps.setObject(1,value);
                    ps.setObject(2,tablename);
                    ps.setObject(3,attname);
                    ps.setInt(4,sn);
                    ps.addBatch();
                    System.out.print("1="+value);
                    System.out.print(",2="+tablename);
                    System.out.print(",3="+attname);
                    System.out.println(",4="+sn);
                    ps.executeBatch();
                }

            }





            ps = createSharedBatchPreparedStatement(ddcs_datasource, ddcs_dstablename, cf);
            ps.setObject(1,value);
            ps.addBatch();
            ps.executeBatch();
        }
    }

    public PreparedStatement getIndexUpdatePreparedStatement() throws SQLException {
        if(indexUpdatePreparedStatement==null){
            StringBuffer sql=new StringBuffer();
            sql.append("update tableindex set ddcs_fieldvalue=? where ddcs_tablename=? and ddcs_sortfieldname=? and sn=?");
           indexUpdatePreparedStatement=connectionConfig.prepareStatement(sql.toString());
        }
        return  indexUpdatePreparedStatement;
    }

    public PreparedStatement createSharedBatchPreparedStatement(String ddcs_datasource,String ddcs_dstablename,ConfiguratorField cf) throws SQLException {
        String key = ddcs_datasource + "_" + ddcs_dstablename;
        PreparedStatement ps = sharedBatchPrepareStatementMap.get(key);
        if(ps==null){
            Connection conn=sharedBatchConnection.get(ddcs_datasource);
            if(conn==null){
                conn = ConnectionFactory.createNonSharedConn(ddcs_datasource);
                sharedBatchConnection.put(ddcs_datasource,conn);
            }

            StringBuffer sql = new StringBuffer("insert into ").append(ddcs_dstablename).append("(").append(cf.getFieldname())
                    .append(") values(?)");
            ps=conn.prepareStatement(sql.toString());
            sharedBatchPrepareStatementMap.put(key,ps);
        }


        return ps;

    }

    public PreparedStatement createConfiguratorPreparedStatement(ConfiguratorField cf) throws SQLException {
        PreparedStatement ps = configuratorPreparedStatementMap.get(cf.getFieldname());
        if(ps==null){

            StringBuffer sql = new StringBuffer("select * from (select sn,ddcs_datasource,ddcs_dstablename,ddcs_ismax,ddcs_fieldvalue from tableindex where ddcs_tablename=? and ddcs_sortfieldname=?")
                    .append(" UNION ALL select null,null,null,null,? from dual) as tableindex order by isnull(ddcs_fieldvalue),ddcs_fieldvalue ");

            if(cf.isSortbyAsc()){
                sql.append(ConfiguratorField.SORTBY_ORACLE_ASC);
            }else{
                sql.append(ConfiguratorField.SORTBY_ORACLE_DESC);
            }
            sql.append(" ,sn asc");


            ps = connectionConfig.prepareStatement(sql.toString());
            configuratorPreparedStatementMap.put(cf.getFieldname(),ps);
        }
        return ps;

    }

}
